package code.google.com.analyticsbot.data;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import code.google.com.analyticsbot.AnalyticsbotServlet;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class WaveData
{
	private static final Logger log = Logger.getLogger(AnalyticsbotServlet.class.getName());

	  @PrimaryKey
	  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	  private Key m_key;

	  @Persistent
	  private int m_version = 1;

	  @Persistent
	  private String m_waveId;

	  @Persistent
	  private String m_waveletId;

	  @Persistent
	  private String m_analyticsbotBlipId = null;

	  //@NotPersistent
	  @Persistent(serialized="true", defaultFetchGroup="true")
	  private Map<String, UserData> m_usersData = new HashMap<String, UserData>();



	  public static String makeKeyString(String waveId, String waveletId)
	  {
		  return waveId + "/" + waveletId;
	  }

	  public WaveData(String waveId, String waveletId)
	  {
		  m_waveId = waveId;
		  m_waveletId = waveletId;

		  String fullName = this.getClass().getName(); // full path including package
		  int i = fullName.lastIndexOf(".")+1;
		  m_key = KeyFactory.createKey(this.getClass().getName().substring(i), makeKeyString(waveId, waveletId));
	  }

	  public int getVersion()
	  {
		  return m_version;
	  }

	  public void incrementVersion()
	  {
		  m_version++;
	  }

	  public String getWaveId()
	  {
		  return m_waveId;
	  }

	  public String getWaveletId()
	  {
		  return m_waveletId;
	  }

	  public String getAnalyticsbotBlipId()
	  {
	      return m_analyticsbotBlipId;
	  }

	  public void setAnalyticsbotBlipId(String blipId)
	  {
	      m_analyticsbotBlipId = blipId;
	  }

	  public UserData getUserData(String userId)
	  {

		  UserData user = m_usersData.get(userId);
		  if(user == null)
		  {
			  user = new UserData(userId);
			  m_usersData.put(userId, user);
			  //m_usersDataList.add(user);
		  }

		  return user;
	  }

	  public Collection<UserData> getUsersData()
	  {
		  return m_usersData.values();
	  }

	@Override
	public String toString()
	{
		return toString("");
	}

	public String toString(String message)
	{
		StringBuffer dump = new StringBuffer();
		if((message != null) && !message.isEmpty())
		{
			dump.append("[" + message + "] ");
		}

		dump.append("Data version=" + m_version + ", wave=" + m_waveId + "/" + m_waveletId + "\n");
		dump.append(CreateRepresentingString("\n"));

		return dump.toString();
	}

	public String toHTML()
	{
		return CreateRepresentingString("<br>");
	}

	private String CreateRepresentingString(String newLine) {
		StringBuffer dump = new StringBuffer();

		dump.append("version=" + m_version);
		int activeUsers = 0;
		int numberOfParticipants=0;
		UserData mostActive = null;
//			dump.append("<br>" + user.toString());

		for(UserData user : m_usersData.values())
		{
			if(!user.getIsParticipant())
			{
				dump.append(newLine);
				dump.append("user "+user.getID()+" is not a participant");
				continue;
			}

			dump.append(newLine);

			dump.append("User "+user.toString());

					int[] userActivityByHours = user.getActivityByHours();
					for (int i=0; i< userActivityByHours.length; i++){
						if (userActivityByHours[i] != 0){
							dump.append(", Submitted " + userActivityByHours[i] + " Blips at hour " + i);
						}
					}
					numberOfParticipants++;

					if (user.isActive()){
						activeUsers++;
					}
					if (user.moreActive(mostActive)){
						mostActive = user;
					}
				}

				dump.append(newLine);
				if(mostActive == null){
					dump.append("No Active user");
				}
				else{
					dump.append("Most Active user is " + mostActive.getID());
				}
				dump.append(newLine);

				int activeUsersPercentage = 0;
				if(numberOfParticipants > 0)
				{
					activeUsersPercentage =(activeUsers*100)/numberOfParticipants;
				}
				dump.append("Percentage of Active Users: " + activeUsersPercentage + "% (" + activeUsers + " / " + numberOfParticipants+")");
		//
//				log.warning(newString.toString());
		//
		return dump.toString();
	}

	public int getWaveActivityBetween(int startHour, int endHour){
		int retVal = 0;
		if((startHour <0) || (startHour > endHour) || (endHour > 23)){
			log.warning("ERROR in getWaveActivityBetween params start="+startHour+ "endHour="+endHour);
			return retVal;
		}
		for(UserData user : m_usersData.values())
		{
			if(!user.getIsParticipant()){
				continue;
			}
			retVal += user.getWaveActivityBetween(startHour, endHour);
		}
	    return retVal;
	}

	public int getNumberOfBlipsCreated(){
		int retVal = 0;
		for(UserData user : m_usersData.values())
		{
			retVal += user.getCreated();
		}
	    return retVal;
	}

	public int getNumberOfParticipants(){
		int retVal = 0;
		for(UserData user : m_usersData.values())
		{
			if(!user.getIsParticipant()){
				continue;
			}
			retVal++;
		}
	    return retVal;
	}

	public int getNumberOfUsersThatLeft(){
		int retVal = 0;
		for(UserData user : m_usersData.values())
		{
			if(user.getIsParticipant()){
				continue;
			}

			retVal++;
		}
	    return retVal;
	}


	public int getActiveParticipantsPercentage(){

		int activeUsers=0;
		int numberOfParticipants=0;
		for(UserData user : m_usersData.values())
		{
			if(!user.getIsParticipant()){
				continue;
			}
			numberOfParticipants++;
			if (user.isActive()){
				activeUsers++;
			}
		}
		int activeUsersPercentage = 0;
		if(numberOfParticipants > 0)
		{
			activeUsersPercentage =(activeUsers*100)/numberOfParticipants;
		}
		return activeUsersPercentage;
	}

	public String getActiveUsersByRank(int minRank, int maxRank){

		List<UserData> rank = getActiveUsers();
		String ans = null;

		Collections.sort(rank, new Comparator<UserData>() {

			@Override
			public int compare(UserData o1, UserData o2) {
				if(o1.moreActive(o2))
				{
					return -1;
				}
				else
				{
					return 1;
				}
			}

		});
		int till = Math.min(maxRank, rank.size()-1);
		for(int i=minRank; i<=till;i++)
		{
			UserData user = rank.get(i);
			String userId = removeDefaultWaveAddress(user.getID());
			if(ans == null)
			{
				ans = userId;
			}
			else
			{
				ans = ans + ", "+userId;
			}
		}

		if(ans==null){
			ans = "None";
		}
		return ans;
	}

	private String removeDefaultWaveAddress(String userId)
	{
		if(userId.toLowerCase().endsWith("@googlewave.com"))
			return userId.substring(0, userId.length()-"@googlewave.com".length());
		else
			return userId;
	}

	private List<UserData> getActiveUsers() {
		List<UserData> activeUsers = new LinkedList<UserData>();
		for(UserData user : m_usersData.values())
		{
			if(!user.getIsParticipant()){
				continue;
			}
			if (user.isActive()){
				activeUsers.add(user);
			}
		}
		return activeUsers;
	}


}

